package com.sensetime.bi.senselink.server.entity;

import com.sensetime.bi.senselink.server.constant.Constant;
import com.sensetime.bi.senselink.server.rtsp.client.RtspClient;
import com.sensetime.bi.senselink.server.util.MD5Util;
import com.sensetime.bi.senselink.server.util.StringUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.handler.codec.rtsp.RtspMethods;
import io.netty.handler.codec.rtsp.RtspVersions;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import static com.sensetime.bi.senselink.server.constant.Constant.SESSION_ID;

@Slf4j
@Getter
@Setter
public class MediaSource {
    String baseUrl;

    String streamId;

    // 与媒体源建立的连接通道
    private Channel connection;

    // 媒体源服务器IP地址
    private String MediaServerIpAddr;

    // 媒体源服务端口
    private Integer MediaServerPort;

    // 视频类型
    private String videoType;

    // 发送给媒体源的序列号
    private int cseq;

    // 音频类型
    private String audioType;

    private String authInfo;

    public void connect() {
        if (connection == null) {
            RtspClient rtspClient = RtspClient.getInstance();
            connection = rtspClient.connect(this.MediaServerIpAddr, this.MediaServerPort);
        }
    }

    public void setSessionId(String sessionId) {
        this.connect();
        if (connection == null) {
            return;
        }
        connection.attr(SESSION_ID).set(sessionId);
    }

    public void sendRequest(RtspRequestMsg request) {
        if (connection == null) {
            log.error("Not connected! cannot sent request!");
            return;
        }
        this.baseUrl = request.getSourceUrl();
        this.streamId = request.getStreamId();

        String[] requestLines = request.getLines();
        StringBuilder stringBuilder = new StringBuilder();
        int idx = 0;
        for (String line : requestLines) {
            if (idx++ == 0) {
                // 请求第一行，替换url
                stringBuilder.append(replaceUrl(line, request));
            } else {
                if (line.trim().toLowerCase().startsWith("cseq")) {
                    stringBuilder.append("CSeq:").append(cseq++);
                    if (this.authInfo != null && this.authInfo.length() > 0) {
                        // 附加认证信息
                        stringBuilder.append(Constant.CRLF).append(authInfo);
                    }
                } else {
                    stringBuilder.append(line);
                }
            }
        }
        String result = stringBuilder.toString();
        this.connection.writeAndFlush(result);
        log.debug("Send request to " + this.getMediaServerIpAddr() +":" + this.getMediaServerPort() +", msg=\n["+ result+"]");
    }

    // DESCRIBE rtsp://10.4.10.177:8104/QWVTYUPKJHL--jbJ5xvUQe41UTUELM8VgeCsdLDL_Nh829IOlEjcB9oQ_h9jo1VqiqsXIFxfGlD8mOC3cXgA_dgUtgRiUUKrPEIaxPHSWXdM0C4OOqcHZAx8= RTSP/1.0
    private String replaceUrl(String line, RtspRequestMsg request) {
        String result = request.getMethod() + StringUtils.SPACE + request.getSourceUrl();
        if (request.getStreamId() != null && request.getStreamId().length() > 0) {
            result += "/" + request.getStreamId();
        }
        result += " RTSP/1.0";
        return result;
    }

    public void setAuthInfo(String authInfo) {
        this.authInfo = authInfo;
    }

    public void doAuth(RtspResponsetMsg msg) {
        /**
         * RTSP/1.0 401 Unauthorized
         * CSeq: 1
         * WWW-Authenticate: Digest realm="Login to 5A03417PAK8C4B3", nonce="adc823765fae16d58a43699f23016802"
         *
         * OPTIONS rtsp://10.4.189.70:554 RTSP/1.0
         * CSeq: 2
         * User-Agent: SFRtsp 0.3
         * Authorization: Digest username="guowen1", realm="Login to 5A03417PAK8C4B3", nonce="adc823765fae16d58a43699f23016802", uri="rtsp://10.4.189.70:554",
         * response="c40af3531e6fc52778f24c26507954df"
         */
//        String uri = "rtsp://10.4.189.70:554";
        String uri = this.baseUrl;
        String response = "";
        String realm = msg.getAuthPairs().get("realm");
        String nonce = msg.getAuthPairs().get("nonce");
        String userName = "guowen1";
        String passwd = "Goodsense";
        if (msg.getAuthType().equals("Digest")) {
            // response= md5( md5(username:realm:password):nonce:md5(public_method:url) );
            String first = userName + ":" + realm + ":" + passwd;
            String second = MD5Util.getMD5(first) + ":" + nonce + ":" + MD5Util.getMD5("OPTIONS:"+uri);
            response = MD5Util.getMD5(second);
        }
         this.authInfo = "Authorization: Digest" + " username=\"guowen1\"," + " realm=\"" + realm
                + "\", nonce=\"" + nonce + "\", uri=\"" + uri + "\", response=\"" + response + "\"";

        String result = RtspMethods.OPTIONS.name() + StringUtils.SPACE + uri + StringUtils.SPACE + RtspVersions.RTSP_1_0.text() + Constant.CRLF +
                "CSeq:" + (this.cseq++) + Constant.CRLF + this.authInfo + Constant.CRLF + Constant.CRLF;
        this.connection.writeAndFlush(result);
        log.debug("resend msg to media: " + this.connection.remoteAddress() + ", msg:\n" + result);
    }

    public void sendRespnse(Object msg) {
        log.debug("send msg to Media service:" + connection.remoteAddress() + "\n") ;
        ChannelFuture channelFuture = connection.writeAndFlush(msg);
        channelFuture.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (!future.isSuccess()) {
                    log.error("from {} send msg to Media service:{} error! reason:{}" , connection.localAddress(), connection.remoteAddress(), future.cause());
                }
            }
        });
    }



    public static void main(String[] args) {
        /**
         * RTSP/1.0 401 Unauthorized
         * CSeq: 1
         * WWW-Authenticate: Digest realm="Login to 5A03417PAK8C4B3", nonce="6902fc59bd67a6619ca363a3c2f71bba"
         *
         * OPTIONS rtsp://10.4.189.70:554 RTSP/1.0
         * CSeq: 2
         * User-Agent: SFRtsp 0.3
         * Authorization: Digest username="guowen1", realm="Login to 5A03417PAK8C4B3", nonce="6902fc59bd67a6619ca363a3c2f71bba", uri="rtsp://10.4.189.70:554",
         * response="488a9c714b1f7f4513fa0c3c84464a03" 488a9c714b1f7f4513fa0c3c84464a03 4a7f1732a0d5db73bfa0dfc5b9ce98f0
         */
//        String url = "\"rtsp://10.4.189.70:554\"";
        String url = "rtsp://10.4.189.70:554";
        String response = "";
//        String realm = "\"Login to 5A03417PAK8C4B3\"";
        String realm = "Login to 5A03417PAK8C4B3";
//        String nonce = "\"6902fc59bd67a6619ca363a3c2f71bba\"";
        String nonce = "5e45f1df214b48e6fdf8c986e1226e51";
        String first = "guowen1" + ":" + realm + ":" + "Goodsense";
        String second = MD5Util.getMD5(first) + ":" + nonce + ":" + MD5Util.getMD5("OPTIONS:"+url);
        response = MD5Util.getMD5(second);
        System.out.println(response);
    }


}
